﻿using System;

namespace MeTool.BarCode
{
    /// <summary>
    /// 表示Code128码,仅使用Code128的B和C模式,线数=元素数*11+35(所谓元素数包含数据和转换符,不包含校验符),于58小票机上可显示16个数字或8个字符
    /// </summary>
    /// <remarks></remarks>
    public static class Code128
    {
        /// <summary>
        /// 根据指定的code128文本返回Code128线码,当参数为""时返回""
        /// </summary>
        /// <param name="code128Text"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string GetLine(string code128Text)
        {
            bool flag = code128Text.Length == 0;
            checked
            {
                string GetLine;
                if (flag)
                {
                    GetLine = "";
                }
                else
                {
                    string dNumeric = "0123456789";
                    bool flag2 = code128Text.Length >= 4 && dNumeric.Contains(code128Text[0].ToString()) && dNumeric.Contains(code128Text[1].ToString()) && dNumeric.Contains(code128Text[2].ToString()) && dNumeric.Contains(code128Text[3].ToString());
                    bool dModeIsC;
                    string dLine;
                    int dCheck;
                    if (flag2)
                    {
                        dModeIsC = true;
                        dLine = mLine[105];
                        dCheck = 105;
                    }
                    else
                    {
                        dModeIsC = false;
                        dLine = mLine[104];
                        dCheck = 104;
                    }
                    int dIndex = 0;
                    int dPos = 0;
                    while (dIndex < code128Text.Length)
                    {
                        bool flag3 = dModeIsC;
                        if (flag3)
                        {
                            bool flag4 = dIndex + 1 <= code128Text.Length - 1 && dNumeric.Contains(code128Text[dIndex].ToString()) && dNumeric.Contains(code128Text[dIndex + 1].ToString());
                            if (flag4)
                            {
                                int dValue = code128Text.Substring(dIndex, 2).ToInteger();
                                dLine += mLine[dValue];
                                dCheck += (dPos + 1) * dValue;
                                dIndex += 2;
                                dPos++;
                            }
                            else
                            {
                                dModeIsC = false;
                                dLine += mLine[100];
                                bool flag5 = code128Text[dIndex] > 126 || code128Text[dIndex] < 32;
                                if (flag5)
                                {
                                    return "";
                                }
                                int dValue2 = code128Text[dIndex] - 32;
                                dLine += mLine[dValue2];
                                dCheck += (dPos + 1) * 100 + (dPos + 2) * dValue2;
                                dIndex++;
                                dPos += 2;
                            }
                        }
                        else
                        {
                            bool flag6 = dIndex + 3 <= code128Text.Length - 1 && dNumeric.Contains(code128Text[dIndex].ToString()) && dNumeric.Contains(code128Text[dIndex + 1].ToString()) && dNumeric.Contains(code128Text[dIndex + 2].ToString()) && dNumeric.Contains(code128Text[dIndex + 3].ToString());
                            if (flag6)
                            {
                                dModeIsC = true;
                                dLine += mLine[99];
                                int dValue3 = code128Text.Substring(dIndex, 2).ToInteger();
                                int dValue4 = code128Text.Substring(dIndex + 2, 2).ToInteger();
                                dLine = dLine + mLine[dValue3] + mLine[dValue4];
                                dCheck += (dPos + 1) * 99 + (dPos + 2) * dValue3 + (dPos + 3) * dValue4;
                                dIndex += 4;
                                dPos += 3;
                            }
                            else
                            {
                                bool flag7 = code128Text[dIndex] > 126 || code128Text[dIndex] < 32;
                                if (flag7)
                                {
                                    return "";
                                }
                                int dValue5 = code128Text[dIndex] - 32;
                                dLine += mLine[dValue5];
                                dCheck += (dPos + 1) * dValue5;
                                dIndex++;
                                dPos++;
                            }
                        }
                    }
                    dLine += mLine[dCheck % 103];
                    dLine += mLine[106];
                    GetLine = dLine;
                }
                return GetLine;
            }
        }

        /// <summary>
        /// 使用小票机内建支持的格式生成条码打印指令
        /// </summary>
        /// <param name="code128Text"></param>
        /// <param name="rowCount"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string GetPosInner(string code128Text, int rowCount = 4)
        {
            if (code128Text.Length <= 2) return "";

            string dText = "";
            dText += "\u001dh" + ((char)checked(24 * (rowCount - 1))).ToString();
            dText += "\u001dkJ" + ((char)code128Text.Length).ToString() + code128Text;
            return dText;
        }

        /// <summary>
        /// 使用列图模式生成条码打印指令
        /// </summary>
        /// <param name="code128Text"></param>
        /// <param name="rowCount"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string GetPosImageCol(string code128Text, int rowCount = 4)
        {
            var dLine = GetLine(code128Text);
            if (dLine.Length == 0) return "";

            var dLeft = (384 - dLine.Length * 3) / 6;
            var dCode = "";
            for (int nn = 0; nn < rowCount; nn++)
            {
                dCode = dCode + "\u001b*!" + ((char)((dLine.Length + dLeft) * 3 % 256)).ToString() + ((char)((dLine.Length + dLeft) * 3 / 256)).ToString();
                dCode += new string('\0', dLeft * 9);
                int num2 = dLine.Length - 1;
                for (int xx = 0; xx <= num2; xx++)
                {
                    if (dLine[xx] == '1')
                    {
                        dCode += new string((char)255, 9);
                    }
                    else
                    {
                        dCode += new string('\0', 9);
                    }
                }
                dCode += "\u001bJ\u0018";
            }
            dCode += "\u001bJ\u0018";
            return dCode;
        }

        /// <summary>
        /// 从13位标准单据号生成等价的12位单据号,12位单据号=2位类号+2位年数+3位月日数+5位顺序号,失败时返回""
        /// </summary>
        /// <param name="id13"></param>
        /// <param name="headCode"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string GetID12FromID13(string id13, int headCode)
        {
            if (id13.Length != 13) return "";

            foreach (char dChar in id13)
            {
                if (!"1234567890".Contains(dChar.ToString())) return "";
            }
            if (headCode < 0 || headCode > 99) return "";

            return headCode.ToString("00") + id13.Substring(2, 2) + (id13.Substring(4, 2).ToInteger() * 32 + id13.Substring(6, 2).ToInteger()).ToString("000") + id13.Substring(8);
        }

        /// <summary>
        /// 从12位压缩分类单据号转换成等价的13位单据号,可保70年正序不错,30年反序不错
        /// </summary>
        /// <param name="id12"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string GetID13FromID12(string id12)
        {
            if (id12.Length != 12) return "";

            foreach (char dChar in id12)
            {
                if (!"1234567890".Contains(dChar.ToString())) return "";
            }
            int dYearNow = DateTime.Now.Year % 100;
            int dYear12 = id12.Substring(2, 2).ToInteger();
            int dMonth = id12.Substring(4, 3).ToInteger();
            int dDay = dMonth % 32;
            dMonth /= 32;
            if (dYearNow >= dYear12)
            {
                if (dYearNow - dYear12 > 70)
                {
                    return (DateTime.Now.Year / 100 + 1).ToString() + dMonth.ToString("00") + dDay.ToString("00") + id12.Substring(7);
                }
                else
                {
                    return (DateTime.Now.Year / 100).ToString() + dMonth.ToString("00") + dDay.ToString("00") + id12.Substring(7);
                }
            }
            else
            {
                if (dYear12 - dYearNow < 30)
                {
                    return (DateTime.Now.Year / 100).ToString() + dMonth.ToString("00") + dDay.ToString("00") + id12.Substring(7);
                }
                else
                {
                    return (DateTime.Now.Year / 100 - 1).ToString() + dMonth.ToString("00") + dDay.ToString("00") + id12.Substring(7);
                }
            }
        }

        /// <summary>
        /// 从13位标准单据号生成等价的14位单据号,14位单据号=2位类号+4位年数+3位月日数+5位顺序号,失败时返回""
        /// </summary>
        /// <param name="id13"></param>
        /// <param name="headCode"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string GetID14FromID13(string id13, int headCode)
        {
            if (id13.Length != 13) return "";
            foreach (char dChar in id13)
            {
                if (!"1234567890".Contains(dChar.ToString())) return "";
            }
            if (headCode < 0 || headCode > 99) return "";

            return headCode.ToString("00") + id13.Substring(2, 2) + (id13.Substring(4, 2).ToInteger() * 32 + id13.Substring(6, 2).ToInteger()).ToString("000") + id13.Substring(8);
        }

        /// <summary>
        /// 从14位分类单据号转换成等价的13位单据号
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string GetID13FromID14(string id14)
        {
            if (id14.Length != 14) return "";

            foreach (char dChar in id14)
            {
                if (!"1234567890".Contains(dChar.ToString())) return "";
            }
            string dYear12 = id14.Substring(2, 4);
            int dMonth = id14.Substring(6, 3).ToInteger();
            int dDay = dMonth % 32;
            return dYear12 + (dMonth / 32).ToString("00") + dDay.ToString("00") + id14.Substring(9);
        }

        private static readonly string[] mLine = new string[]
        {
            "11011001100",
            "11001101100",
            "11001100110",
            "10010011000",
            "10010001100",
            "10001001100",
            "10011001000",
            "10011000100",
            "10001100100",
            "11001001000",
            "11001000100",
            "11000100100",
            "10110011100",
            "10011011100",
            "10011001110",
            "10111001100",
            "10011101100",
            "10011100110",
            "11001110010",
            "11001011100",
            "11001001110",
            "11011100100",
            "11001110100",
            "11101101110",
            "11101001100",
            "11100101100",
            "11100100110",
            "11101100100",
            "11100110100",
            "11100110010",
            "11011011000",
            "11011000110",
            "11000110110",
            "10100011000",
            "10001011000",
            "10001000110",
            "10110001000",
            "10001101000",
            "10001100010",
            "11010001000",
            "11000101000",
            "11000100010",
            "10110111000",
            "10110001110",
            "10001101110",
            "10111011000",
            "10111000110",
            "10001110110",
            "11101110110",
            "11010001110",
            "11000101110",
            "11011101000",
            "11011100010",
            "11011101110",
            "11101011000",
            "11101000110",
            "11100010110",
            "11101101000",
            "11101100010",
            "11100011010",
            "11101111010",
            "11001000010",
            "11110001010",
            "10100110000",
            "10100001100",
            "10010110000",
            "10010000110",
            "10000101100",
            "10000100110",
            "10110010000",
            "10110000100",
            "10011010000",
            "10011000010",
            "10000110100",
            "10000110010",
            "11000010010",
            "11001010000",
            "11110111010",
            "11000010100",
            "10001111010",
            "10100111100",
            "10010111100",
            "10010011110",
            "10111100100",
            "10011110100",
            "10011110010",
            "11110100100",
            "11110010100",
            "11110010010",
            "11011011110",
            "11011110110",
            "11110110110",
            "10101111000",
            "10100011110",
            "10001011110",
            "10111101000",
            "10111100010",
            "11110101000",
            "11110100010",
            "10111011110",
            "10111101110",
            "11101011110",
            "11110101110",
            "11010000100",
            "11010010000",
            "11010011100",
            "1100011101011"
        };

        //private const int mWordBOff = 32;
        //private const int mStartBID = 104;
        //private const int mStartCID = 105;
        //private const int mCodeBID = 100;
        //private const int mCodeCID = 99;
        //private const int mStopID = 106;
    }
}
